#include "wiota_subf.h"
#include "config_api.h"
#include "uc_wiota_api.h"
#include "userid_manager.h"
#include <rtdevice.h>
#define DBG_ENABLE
#define DBG_SECTION_NAME "subf"
#include "uc_log.h"

// WIoTa子频数据计数检测周期，1秒
#define WIOTA_SUBF_CNT_PERIOD (1000)

// WIoTa上行子帧数据计数检测定时器
static rt_timer_t g_subf_cnt_timer = RT_NULL;
// WIoTa上行子帧数据计数列表
static rt_list_t g_ul_subf_list = {RT_NULL};
// 首次收到子帧数据标志
static unsigned char g_first_access = 1;
// 在线的用户个数
static unsigned char g_user_number = 0;

/**
 * @brief 定时器回调函数，检测子帧数据计数，如果每增加则认为终端离线
 *
 * @param para 定时器创建时传入的参数
 */
static void wiota_subf_cnt_timer_func(void *para)
{
    ul_subf_node_t *cur_node = RT_NULL;

    rt_list_for_each_entry(cur_node, &g_ul_subf_list, node)
    {
        if (cur_node->subf_cnt == cur_node->last_subf_cnt && cur_node->is_online)
        {
            cur_node->subf_cnt = 0;
            cur_node->is_online = 0;
            TRACE_I("user 0x%x offline", cur_node->dev_id);
            g_user_number--;
            if (g_user_number == 0)
            {
                rt_timer_stop(g_subf_cnt_timer);
                TRACE_W("all user is offline");
            }
        }

        cur_node->last_subf_cnt = cur_node->subf_cnt;
    }
}

/**
 * @brief 清除子帧数据计数列表
 *
 */
static void wiota_subf_node_clear(void)
{
    ul_subf_node_t *node = RT_NULL;
    rt_list_t *next_node = g_ul_subf_list.next;

    while (next_node != &g_ul_subf_list)
    {
        node = rt_list_entry(next_node, ul_subf_node_t, node);
        if (node)
        {
            rt_free(node);
        }
        next_node = next_node->next;
    }
    rt_list_init(&g_ul_subf_list);
}

/**
 * @brief 根据wiota_id查找一个节点
 *
 * @param wiota_id         wiota_id
 * @return ul_subf_node_t* 节点指针
 */
static ul_subf_node_t *wiota_subf_find_node(unsigned int wiota_id)
{
    ul_subf_node_t *cur_node = RT_NULL;

    rt_list_for_each_entry(cur_node, &g_ul_subf_list, node)
    {
        if (cur_node->wiota_id == wiota_id)
        {
            return cur_node;
        }
    }

    return RT_NULL;
}

/**
 * @brief 获取一个节点，如果不存在则创建
 *
 * @param wiota_id         wiota_id
 * @return ul_subf_node_t* 节点指针
 */
ul_subf_node_t *wiota_subf_get_node(unsigned int wiota_id)
{
    ul_subf_node_t *node = RT_NULL;

    node = wiota_subf_find_node(wiota_id);
    if (node == RT_NULL)
    {
        node = rt_malloc(sizeof(ul_subf_node_t));
        RT_ASSERT(node);
        rt_memset(node, 0, sizeof(ul_subf_node_t));

        node->wiota_id = wiota_id;
        node->dev_id = manager_query_dev_id_by_wiota_id(wiota_id);
        node->is_online = 1;

        g_user_number++;
        if (g_user_number == 1)
        {
            rt_timer_start(g_subf_cnt_timer);
        }
        rt_list_insert_after(&g_ul_subf_list, &node->node);
        TRACE_I("user 0x%x online, num %d", node->dev_id, g_user_number);
    }
    else
    {
        if (node->is_online == 0)
        {
            node->is_online = 1;

            g_user_number++;
            if (g_user_number == 1)
            {
                rt_timer_start(g_subf_cnt_timer);
            }
            TRACE_I("user 0x%x online, num %d", node->dev_id, g_user_number);
        }
    }
    node->subf_cnt++;

    return node;
}

/**
 * @brief WIoTa子帧模式初始化
 *
 */
void wiota_subf_mode_init(void)
{
    wiota_subf_mode_cfg_t *subf_cfg = uc_static_get_wiota_subf_mode_cfg();
    wiota_rate_cfg_t *rate_cfg = uc_static_get_wiota_rate_cfg();
    uc_subf_cfg_t cfg = {0};

    if (subf_cfg->ul_subf_mode)
    {
        cfg.block_size = subf_cfg->block_size;
        cfg.send_round = subf_cfg->dl_subf_send_round;
        uc_wiota_set_subframe_mode_cfg(&cfg);
        uc_wiota_set_data_rate(UC_RATE_CRC_TYPE, rate_cfg->crc_type);

        g_subf_cnt_timer = rt_timer_create("cnt_timer",
                                           wiota_subf_cnt_timer_func,
                                           RT_NULL,
                                           WIOTA_SUBF_CNT_PERIOD,
                                           RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_SOFT_TIMER);
        RT_ASSERT(g_subf_cnt_timer);
        rt_list_init(&g_ul_subf_list);
        TRACE_D("wiota_subf_mode_init suc");
    }
}

/**
 * @brief WIoTa子帧模式反初始化
 *
 */
void wiota_subf_mode_deinit(void)
{
    wiota_subf_mode_cfg_t *subf_cfg = uc_static_get_wiota_subf_mode_cfg();

    if (subf_cfg->ul_subf_mode)
    {
        if (g_subf_cnt_timer)
        {
            rt_timer_stop(g_subf_cnt_timer);
            rt_timer_delete(g_subf_cnt_timer);
            g_subf_cnt_timer = RT_NULL;
        }
        wiota_subf_node_clear();
        g_user_number = 0;
        g_first_access = 0;
        TRACE_D("wiota_subf_mode_deinit suc");
    }
}

/**
 * @brief 获取子帧模式下的在线用户个数
 *
 * @return unsigned char 在线用户个数
 */
unsigned char wiota_get_user_number(void)
{
    return g_user_number;
}

/**
 * @brief 获取是否是第一次收到子帧数据
 *
 * @return unsigned char 是否是第一次收到子帧数据
 */
unsigned char wiota_get_first_access(void)
{
    return g_first_access;
}

/**
 * @brief 重置是否是第一次收到子帧数据标志
 *
 */
void wiota_reset_first_access(void)
{
    g_first_access = 0;
}